package com.harmony.pilot.knowledge.service;

import com.harmony.pilot.common.dto.CompletionItem;
import com.harmony.pilot.data.dto.ASTSymbol;
import com.harmony.pilot.data.dto.SymbolQueryRequest;
import com.harmony.pilot.knowledge.entity.CodeSnippet;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * CodeQL集成服务
 * 在知识库服务中集成CodeQL AST查询能力，用于增强智能补全
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CodeQLIntegrationService {
    
    private final WebClient codeQLClient;
    
    @Value("${codeql.data-service-url:http://localhost:8085}")
    private String dataServiceUrl;
    
    public CodeQLIntegrationService(@Value("${codeql.data-service-url:http://localhost:8085}") String dataServiceUrl) {
        this.codeQLClient = WebClient.builder()
                .baseUrl(dataServiceUrl)
                .build();
    }
    
    /**
     * 使用CodeQL AST增强补全结果
     * 
     * @param keyword 关键词
     * @param context 上下文代码
     * @param filePath 当前文件路径
     * @param kbResults 知识库搜索结果
     * @return 融合后的补全结果
     */
    public List<CompletionItem> enhanceCompletionsWithAST(
            String keyword, 
            String context, 
            String filePath,
            List<CodeSnippet> kbResults) {
        
        log.info("Enhancing completions with CodeQL AST: keyword={}", keyword);
        
        List<CompletionItem> enhancedResults = new ArrayList<>();
        
        try {
            // 1. 从CodeQL获取AST信息
            SymbolQueryRequest request = new SymbolQueryRequest();
            request.setSymbol(keyword);
            request.setMaxResults(20);
            
            SymbolQueryRequest.Context queryContext = new SymbolQueryRequest.Context();
            queryContext.setFilePath(filePath);
            queryContext.setCode(context);
            request.setContext(queryContext);
            
            List<ASTSymbol> astSymbols = codeQLClient.post()
                    .uri("/data/codeql/symbols/ast")
                    .bodyValue(request)
                    .retrieve()
                    .bodyToFlux(ASTSymbol.class)
                    .collectList()
                    .block();
            
            if (astSymbols == null || astSymbols.isEmpty()) {
                log.debug("No AST symbols found, using KB results only");
                return convertToCompletionItems(kbResults);
            }
            
            // 2. 转换AST结果为CompletionItem（优先级高）
            List<CompletionItem> astItems = astSymbols.stream()
                    .map(this::convertASTSymbolToItem)
                    .collect(Collectors.toList());
            
            enhancedResults.addAll(astItems);
            
            // 3. 添加知识库结果（补充，避免重复）
            for (CodeSnippet snippet : kbResults) {
                boolean exists = enhancedResults.stream()
                        .anyMatch(item -> item.getLabel().equals(snippet.getSummary()));
                if (!exists) {
                    enhancedResults.add(convertSnippetToItem(snippet));
                }
            }
            
            // 4. 限制结果数
            if (enhancedResults.size() > 20) {
                enhancedResults = enhancedResults.subList(0, 20);
            }
            
            log.info("Enhanced completions: {} AST + {} KB = {} total", 
                    astItems.size(), kbResults.size(), enhancedResults.size());
            
        } catch (Exception e) {
            log.warn("Failed to enhance with CodeQL AST, using KB results only", e);
            return convertToCompletionItems(kbResults);
        }
        
        return enhancedResults;
    }
    
    /**
     * 转换AST符号为CompletionItem
     */
    private CompletionItem convertASTSymbolToItem(ASTSymbol symbol) {
        CompletionItem item = new CompletionItem();
        item.setLabel(symbol.getName());
        item.setDetail(symbol.getSignature() != null ? symbol.getSignature() : symbol.getQualifiedName());
        item.setDocumentation(String.format("Type: %s\nLocation: %s:%d:%d", 
                symbol.getType(), 
                symbol.getFilePath(), 
                symbol.getLine(), 
                symbol.getColumn()));
        item.setKind(mapASTTypeToCompletionKind(symbol.getType()));
        item.setInsertText(symbol.getName());
        item.setSource("codeql-ast"); // 标记来源
        item.setConfidence(0.95); // AST结果置信度更高
        return item;
    }
    
    /**
     * 转换CodeSnippet为CompletionItem
     */
    private CompletionItem convertSnippetToItem(CodeSnippet snippet) {
        CompletionItem item = new CompletionItem();
        item.setLabel(snippet.getSummary());
        item.setDetail(snippet.getFilePath());
        item.setDocumentation(snippet.getContent());
        item.setKind(mapSnippetTypeToCompletionKind(snippet.getSnippetType()));
        item.setInsertText(snippet.getSummary());
        item.setSource("knowledge-base");
        item.setConfidence(0.80);
        return item;
    }
    
    /**
     * 转换CodeSnippet列表为CompletionItem列表
     */
    private List<CompletionItem> convertToCompletionItems(List<CodeSnippet> snippets) {
        return snippets.stream()
                .map(this::convertSnippetToItem)
                .collect(Collectors.toList());
    }
    
    /**
     * 映射AST类型到补全类型
     */
    private String mapASTTypeToCompletionKind(String astType) {
        if (astType == null) {
            return "Text";
        }
        switch (astType.toLowerCase()) {
            case "function": return "Function";
            case "class": return "Class";
            case "method": return "Method";
            case "variable": return "Variable";
            case "field": return "Field";
            default: return "Text";
        }
    }
    
    /**
     * 映射片段类型到补全类型
     */
    private String mapSnippetTypeToCompletionKind(String snippetType) {
        if (snippetType == null) {
            return "Text";
        }
        switch (snippetType) {
            case "FUNCTION": return "Function";
            case "CLASS": return "Class";
            case "METHOD": return "Method";
            case "FIELD": return "Field";
            default: return "Text";
        }
    }
    
    /**
     * CompletionItem内部类（临时，应该从common模块引入）
     */
    public static class CompletionItem {
        private String label;
        private String detail;
        private String documentation;
        private String kind;
        private String insertText;
        private String source;
        private Double confidence;
        
        // Getters and Setters
        public String getLabel() { return label; }
        public void setLabel(String label) { this.label = label; }
        
        public String getDetail() { return detail; }
        public void setDetail(String detail) { this.detail = detail; }
        
        public String getDocumentation() { return documentation; }
        public void setDocumentation(String documentation) { this.documentation = documentation; }
        
        public String getKind() { return kind; }
        public void setKind(String kind) { this.kind = kind; }
        
        public String getInsertText() { return insertText; }
        public void setInsertText(String insertText) { this.insertText = insertText; }
        
        public String getSource() { return source; }
        public void setSource(String source) { this.source = source; }
        
        public Double getConfidence() { return confidence; }
        public void setConfidence(Double confidence) { this.confidence = confidence; }
    }
}

